package com.dlc.shop.distribution.common.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.PhoneUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dlc.shop.bean.enums.EnterpriseApplyType;
import com.dlc.shop.bean.enums.EnterprisePayStatus;
import com.dlc.shop.bean.model.EnterprisePay;
import com.dlc.shop.bean.vo.DistributionConfigVO;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.constants.SegmentIdKey;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.i18n.I18nMessage;
import com.dlc.shop.common.util.Arith;
import com.dlc.shop.common.util.PrincipalUtil;
import com.dlc.shop.dao.EnterprisePayMapper;
import com.dlc.shop.distribution.common.constants.DistributionAudit;
import com.dlc.shop.distribution.common.constants.DistributionWithdrawCashStateEnum;
import com.dlc.shop.distribution.common.dao.DistributionUserWalletBillMapper;
import com.dlc.shop.distribution.common.dao.DistributionUserWalletMapper;
import com.dlc.shop.distribution.common.dao.DistributionWithdrawCashMapper;
import com.dlc.shop.distribution.common.dto.DistributionWithdrawCashDto;
import com.dlc.shop.distribution.common.model.DistributionUser;
import com.dlc.shop.distribution.common.model.DistributionUserWallet;
import com.dlc.shop.distribution.common.model.DistributionUserWalletBill;
import com.dlc.shop.distribution.common.model.DistributionWithdrawCash;
import com.dlc.shop.distribution.common.param.DistributionParam;
import com.dlc.shop.distribution.common.param.RangeTimeParam;
import com.dlc.shop.distribution.common.service.DistributionWithdrawCashService;
import com.dlc.shop.security.common.enums.SocialType;
import com.dlc.shop.security.common.model.AppConnect;
import com.dlc.shop.security.common.service.AppConnectService;
import com.dlc.shop.service.SegmentService;
import com.dlc.shop.service.SysConfigService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author lgh on 2019/04/01.
 */
@Service
@RequiredArgsConstructor
public class DistributionWithdrawCashServiceImpl extends ServiceImpl<DistributionWithdrawCashMapper, DistributionWithdrawCash> implements DistributionWithdrawCashService {
    public static final int MONTH_DAY = 30;

    private final DistributionWithdrawCashMapper distributionWithdrawCashMapper;

    private final SysConfigService sysConfigService;

    private final DistributionUserWalletMapper distributionUserWalletMapper;

    private final DistributionUserWalletBillMapper distributionUserWalletBillMapper;

    private final SegmentService segmentService;

    private final EnterprisePayMapper enterprisePayMapper;
    private final AppConnectService appConnectService;

    @Override
    public IPage<DistributionWithdrawCash> distributionWithdrawCashsPage(Page page, Long shopId, RangeTimeParam rangeTimeParam, DistributionParam distributionParam, DistributionWithdrawCash distributionWithdrawCash) {
        IPage<DistributionWithdrawCash> cashsPage = distributionWithdrawCashMapper.distributionWithdrawCashsPage(page, shopId, rangeTimeParam, distributionParam, distributionWithdrawCash);
        for (DistributionWithdrawCash record : cashsPage.getRecords()) {
            record.getDistributionUser().setUserMobile(PhoneUtil.hideBetween(record.getDistributionUser().getUserMobile()).toString());
            if (PrincipalUtil.isMobile(record.getDistributionUser().getNickName())) {
                record.getDistributionUser().setNickName(PhoneUtil.hideBetween(record.getDistributionUser().getNickName()).toString());
            }
        }
        return cashsPage;
    }

    @Override
    public IPage<DistributionWithdrawCashDto> distributionWithdrawCashDtoPageByUserId(Page page, Long distributionUserId) {
        return distributionWithdrawCashMapper.distributionWithdrawCashDtoPageByUserId(page, distributionUserId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(Double amount, DistributionUser distributionUser) {
        List<AppConnect> appConnectList = appConnectService.list(new LambdaQueryWrapper<AppConnect>()
                .eq(AppConnect::getUserId, distributionUser.getUserId())
                .eq(AppConnect::getAppId, SocialType.MA.value())
                .orderByDesc(AppConnect::getId));
        AppConnect appConnect = new AppConnect();
        if(CollectionUtil.isNotEmpty(appConnectList)){
            appConnect = appConnectList.get(0);
        }
        //获取店铺提现设置
        DistributionConfigVO distributionConfigVO = sysConfigService.getSysConfigObject(Constant.DISTRIBUTION_CONFIG, DistributionConfigVO.class);
        //结算提现金额是否超出限制
        if (amount > distributionConfigVO.getAmountMax()) {
            // 提现金额大于最大提现金额
            throw new YamiShopBindException("yami.distribution.fee.than.error");
        }
        if (amount < distributionConfigVO.getAmountMin()) {
            // 提现金额小于最小提现金额
            throw new YamiShopBindException("yami.distribution.fee.less.error");
        }

        // 判断提现频率和次数
        checkCalendarAndNum(distributionConfigVO, distributionUser);
        //获取用户的钱包数据
        DistributionUserWallet distributionUserWallet = distributionUserWalletMapper.selectOne(new LambdaQueryWrapper<DistributionUserWallet>()
                .eq(DistributionUserWallet::getDistributionUserId, distributionUser.getDistributionUserId()));
        //判断提现金额 是否大于钱包金额
        if (distributionUserWallet.getSettledAmount() < amount) {
            // 提现失败,余额不足
            throw new YamiShopBindException("yami.distribution.balance.not.enough");
        }

        //扣除可提现余额
        distributionUserWallet.setSettledAmount(Arith.sub(distributionUserWallet.getSettledAmount(), amount));

        //插入一条提现记录
        DistributionWithdrawCash distributionWithdrawCash = createCash(amount, distributionUserWallet, appConnect, distributionConfigVO);

        // 存入提现记录
        distributionWithdrawCashMapper.insert(distributionWithdrawCash);

        // 增加钱包流水记录
        distributionUserWalletBillMapper.insert(new DistributionUserWalletBill(distributionUserWallet, "用户提现", "User withdrawals", 0.0, -amount, 0.0, 0.0, 0));

        //修改钱包
        int updateAmount = distributionUserWalletMapper.updateAmount(amount, distributionUser.getDistributionUserId());
        if (updateAmount < 1) {
            // 提现失败,余额不足
            throw new YamiShopBindException("yami.distribution.balance.not.enough");
        }

        // 判断人工审核后线下打款
        if (distributionConfigVO.getWithdrawal().equals(DistributionAudit.TWithdrawals_TWO.getValue())) {
            return;
        }
        // 判断用户是否有openId没有提示绑定微信小程序
        if (CollectionUtil.isEmpty(appConnectList) || StringUtils.isBlank(appConnect.getBizUserId()) || StringUtils.isBlank(appConnect.getUserId())) {
            throw new YamiShopBindException("yami.distribution.user.withdrawals");
        }
        if (distributionConfigVO.getWithdrawal().equals(DistributionAudit.Withdrawals_ZERO.getValue())) {
            enterprisePay(distributionWithdrawCash, appConnect.getUserId(), appConnect.getBizUserId(), EnterprisePayStatus.APPLY.getValue());
        }

    }

    private void checkCalendarAndNum(DistributionConfigVO distributionConfigVO, DistributionUser distributionUser) {
        //获取店铺设置的提现频率算出时间区间
        Calendar calendar = Calendar.getInstance();
        int monthDay = MONTH_DAY;
        if (distributionConfigVO.getFrequency() == monthDay) {
            //每月的第一天
            calendar.set(Calendar.DAY_OF_MONTH, 1);
        } else {
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - distributionConfigVO.getFrequency());
        }
        //将小时至0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        calendar.set(Calendar.MINUTE, 0);
        //将秒至0
        calendar.set(Calendar.SECOND, 0);
        //将毫秒至0
        calendar.set(Calendar.MILLISECOND, 0);
        RangeTimeParam rangeTimeParam = new RangeTimeParam(calendar.getTime(), new Date());
        //获取用户最近的提现次数，判断是否能够提现
        if (distributionWithdrawCashMapper.getCountByRangeTimeAndDistributionUserId(rangeTimeParam, distributionUser.getDistributionUserId()) >= distributionConfigVO.getNumber()) {
            // 提现次数为
            String message = I18nMessage.getMessage("yami.distribution.cash.num");
            String day = I18nMessage.getMessage("yami.day");
            String num = I18nMessage.getMessage("yami.constant.num");
            if (distributionConfigVO.getFrequency() == monthDay) {
                String month = I18nMessage.getMessage("yami.distribution.cash.month");
                throw new YamiShopBindException(message + month + distributionConfigVO.getNumber() + num);
            } else {
                throw new YamiShopBindException(message + distributionConfigVO.getFrequency() + day + distributionConfigVO.getNumber() + num);
            }
        }
    }

    private DistributionWithdrawCash createCash(Double amount, DistributionUserWallet distributionUserWallet, AppConnect appConnect, DistributionConfigVO distributionConfigVO) {
        Date now = new Date();
        DistributionWithdrawCash distributionWithdrawCash = new DistributionWithdrawCash();
        distributionWithdrawCash.setBizUserId(appConnect.getBizUserId());
        distributionWithdrawCash.setCreateTime(now);
        distributionWithdrawCash.setWalletId(distributionUserWallet.getWalletId());
        distributionWithdrawCash.setAmount(amount);
        distributionWithdrawCash.setMerchantOrderId(String.valueOf(segmentService.getSegmentId(SegmentIdKey.ALLINPAY_WITHDRAW_CASH)));
        distributionWithdrawCash.setVersion(0);
        distributionWithdrawCash.setUpdateTime(now);
        // 暂时没有手续费
        distributionWithdrawCash.setFee(0.0);

        // 判断人工审核后线下打款
        if (distributionConfigVO.getWithdrawal().equals(DistributionAudit.TWithdrawals_TWO.getValue())) {
            //设置为手动提现
            distributionWithdrawCash.setType(0);
            distributionWithdrawCash.setMoneyFlow(0);
        } else {
            distributionWithdrawCash.setType(1);
            distributionWithdrawCash.setMoneyFlow(1);
        }
        distributionWithdrawCash.setState(DistributionWithdrawCashStateEnum.APPLY.getValue());
        if (distributionConfigVO.getWithdrawal().equals(DistributionAudit.Withdrawals_ZERO.getValue())) {
            distributionWithdrawCash.setState(DistributionWithdrawCashStateEnum.CASH_SUCCESS.getValue());
        }
        return distributionWithdrawCash;
    }

    @Override
    public void enterprisePay(DistributionWithdrawCash distributionWithdrawCash, String userId, String openId, Integer status) {
        // 添加商家转账记录
        EnterprisePay enterprisePay = new EnterprisePay();
        enterprisePay.setStatus(status);
        enterprisePay.setType(EnterpriseApplyType.DISTRIBUTION_WITHDRAW.value());
        enterprisePay.setBizId(distributionWithdrawCash.getWithdrawCashId());
        enterprisePay.setUserId(userId);
        enterprisePay.setOpenId(openId);
        enterprisePay.setVersion(0);
        enterprisePay.setEntPayOrderNo(segmentService.getDateFormatSegmentId(SegmentIdKey.DISTRIBUTION_PAY_ORDER_NO));
        enterprisePay.setUpdateTime(new Date());
        enterprisePay.setCreateTime(new Date());
        enterprisePay.setAmount(distributionWithdrawCash.getAmount());
        enterprisePayMapper.insert(enterprisePay);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWithDraw(DistributionWithdrawCash distributionWithdrawCash, DistributionUserWallet wallet, DistributionUser distributionUser) {
        int count = distributionWithdrawCashMapper.updateSuccess(distributionWithdrawCash.getWithdrawCashId());
        if (count < 1) {
            throw new YamiShopBindException("提现状态已经发生改变，请勿重复操作");
        }

        //获取店铺提现设置
        if (!distributionWithdrawCash.getMoneyFlow().equals(DistributionAudit.Withdrawals_ONE.getValue())
            || Objects.equals(distributionWithdrawCash.getType(), 0)) {
            return;
        }

        String userId = distributionUser.getUserId();
        // 添加企业支付记录
        enterprisePay(distributionWithdrawCash, userId, distributionWithdrawCash.getBizUserId(), EnterprisePayStatus.APPLY.getValue());
    }

    @Override
    public Integer getCountByRangeTimeAndDistributionUserId(RangeTimeParam rangeTimeParam, Long distributionUserId) {
        return distributionWithdrawCashMapper.getCountByRangeTimeAndDistributionUserId(rangeTimeParam, distributionUserId);
    }

    @Override
    public Double getUserTotalWithdrawCash(Long walletId) {
        return distributionWithdrawCashMapper.getUserTotalWithdrawCash(walletId);
    }


}
